package edu.uwm.cs552;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.DecimalFormat;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.WindowConstants;

import edu.uwm.cs552.util.JLoggerList;

/**
 * Window for playing train game.
 */
public class PlayerFrame extends JFrame {

	/**
	 * Keep Eclipse happy
	 */
	private static final long serialVersionUID = 1L;
	
	private static DecimalFormat moneyFormat = new DecimalFormat("M$ #.00");
	private static String formatMoney(double m) {
		return "Money: " + moneyFormat.format(m);
	}

	private final RailGame game;
	private final Player player;
	
	private JLabel money = new JLabel(formatMoney(0));
	private JButton move = new JButton("Move");
	private JButton clear = new JButton("Clear Log");
	private JComboBox actions = new JComboBox(PlayerEditAction.values());

	private PlayerPanel playerPanel;
	
	/**
	 * Create a window for a player (or for the game supervisor).
	 * The game stops when the supervisor window is closed.
	 * @param g game, must not be null
	 * @param p player, may be null for the game supervisor
	 * @param b board being used
	 */
	public PlayerFrame(final RailGame g, final Player p, final HexBoard b) {
		super(p == null ? "Game Control Panel" : ("Player " + p.getIndex()));
		game = g;
		player = p;
		JPanel contentPane = new JPanel();
		this.setContentPane(contentPane);
		contentPane.setLayout(new BorderLayout());
		playerPanel = new PlayerPanel(g,p,b);
		contentPane.add(new JScrollPane(playerPanel),BorderLayout.CENTER);
		JPanel controlPanel = new JPanel();
		contentPane.add(controlPanel,BorderLayout.NORTH);
		controlPanel.add(new ScaleComboBox(playerPanel));
		if (p == null) {
			this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
			g.addObserver(new Observer() {
				private boolean active = true;
				public void update(Observable o, Object arg) {
					if (active) {
						try {
							active = false;
							game.checkTime();
						} finally {
							active = true;
						}
					}
				}
			});
		} else {
			final JLoggerList loggerList = new JLoggerList(p.getLogger());
			final JScrollPane scrollPane = new JScrollPane(loggerList);
			contentPane.add(scrollPane,BorderLayout.SOUTH);
			controlPanel.add(move);
			controlPanel.add(actions);
			controlPanel.add(clear);
			controlPanel.add(money);
			money.setText(formatMoney(p.getMoney()));
			this.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);

			move.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					if (player.hasTime()) player.move();
				}
			});
			
			clear.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					loggerList.clear();
				}
			});
			
			p.addObserver(new Observer() {
				public void update(Observable o, Object arg) {
					if (o == player) {
						if (arg instanceof Double) money.setText(formatMoney(player.getMoney()));
						move.setEnabled(player.hasTime());
					}
				}
			});
			
			MouseAdapter mouseListener = new MouseAdapter() {
				@Override
				public void mouseDragged(MouseEvent arg0) {
					mouseAction(arg0);
				}
				@Override
				public void mousePressed(MouseEvent arg0) {
					mouseAction(arg0);
				}
			};
			playerPanel.addMouseListener(mouseListener);
			playerPanel.addMouseMotionListener(mouseListener);
		}
		setSize(500,300);
	}
	
	private void mouseAction(MouseEvent arg) {
		PlayerEditAction a = (PlayerEditAction)actions.getSelectedItem();
		a.apply(player, arg.getPoint(), playerPanel.getScale());
	}
}
